package com.kmxd.ams.app.archive;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.kmxd.ams.client.archive.IArchiveAuthRuleSvc;
import com.kmxd.ams.client.archive.dto.ArchiveAuthRuleAddDTO;
import com.kmxd.ams.client.archive.dto.ArchiveAuthRuleEditDTO;
import com.kmxd.ams.client.archive.dto.ArchiveAuthRuleQueryDTO;
import com.kmxd.ams.client.archive.vo.ArchiveAuthRuleListVO;
import com.kmxd.ams.client.archive.vo.ArchiveAuthRuleVO;
import com.kmxd.ams.core.common.bo.ConditionBO;
import com.kmxd.ams.core.common.bo.LoginUser;
import com.kmxd.ams.core.common.constant.ErrorCode;
import com.kmxd.ams.core.common.query.QueryGen;
import com.kmxd.ams.core.exception.BizTipException;
import com.kmxd.ams.core.util.IdUtil;
import com.kmxd.ams.core.util.SecurityUtil;
import com.kmxd.ams.infra.archive.entity.ArchiveAuthRule;
import com.kmxd.ams.infra.archive.mapper.ArchiveAuthRuleMapper;
import com.kmxd.ams.infra.system.entity.SysUserPost;
import com.kmxd.ams.infra.system.mapper.SysUserPostMapper;
import java.util.*;
import java.util.stream.Collectors;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 特殊利用授权 服务实现类
 *
 * @author nickbi
 * @since 2022-07-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class ArchiveAuthRuleSvcImpl extends ServiceImpl<ArchiveAuthRuleMapper, ArchiveAuthRule>
    implements IArchiveAuthRuleSvc {

  private SysUserPostMapper sysUserPostMapper;

  @Override
  public Page<ArchiveAuthRuleListVO> selectPage(Page reqPage, ArchiveAuthRuleQueryDTO req) {
    LambdaQueryWrapper<ArchiveAuthRule> queryWrapper =
        QueryGen.init(new QueryWrapper<ArchiveAuthRule>(), req).lambda();
    Page<ArchiveAuthRule> page = baseMapper.selectPage(reqPage, queryWrapper);
    Page<ArchiveAuthRuleListVO> voPage = BeanUtil.copyProperties(page, Page.class);
    voPage.setRecords(BeanUtil.copyToList(page.getRecords(), ArchiveAuthRuleListVO.class));
    return voPage;
  }

  @Override
  public List<ArchiveAuthRuleListVO> selectList(ArchiveAuthRuleQueryDTO req) {
    LambdaQueryWrapper<ArchiveAuthRule> queryWrapper =
        QueryGen.init(new QueryWrapper<ArchiveAuthRule>(), req).lambda();
    List<ArchiveAuthRule> list = baseMapper.selectList(queryWrapper);
    return BeanUtil.copyToList(list, ArchiveAuthRuleListVO.class);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void add(ArchiveAuthRuleAddDTO req) {
    req.setFondsId(
        ObjectUtil.isNotEmpty(req.getFondsId()) ? req.getFondsId() : SecurityUtil.getFondsId());
    ArchiveAuthRule entity = BeanUtil.copyProperties(req, ArchiveAuthRule.class);
    baseMapper.insert(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void edit(ArchiveAuthRuleEditDTO req) {
    ArchiveAuthRule entity = BeanUtil.copyProperties(req, ArchiveAuthRule.class);
    baseMapper.updateById(entity);
  }

  @Override
  @Transactional(rollbackFor = Exception.class)
  public void remove(String ids) {
    Set<Long> idList = IdUtil.split(ids);
    this.baseMapper.deleteBatchIds(idList);
  }

  @Override
  public ArchiveAuthRuleVO view(String id) {
    ArchiveAuthRule entity = baseMapper.selectById(id);
    return BeanUtil.copyProperties(entity, ArchiveAuthRuleVO.class);
  }

  @Override
  public LinkedHashSet<ConditionBO> getAuthRuleByUser(LoginUser loginUser) {
    loginUser = ObjUtil.isEmpty(loginUser) ? SecurityUtil.getLoginUser() : loginUser;
    if (ObjUtil.isEmpty(loginUser)) {
      throw BizTipException.instance(ErrorCode.NOT_FOUND, "找不到用户对象信息");
    }
    LinkedHashSet<ConditionBO> condition = new LinkedHashSet<>();
    try {
      List<ArchiveAuthRule> list = this.list();
      // 查询我这个用户的所有岗位
      LambdaQueryWrapper<SysUserPost> wq = Wrappers.lambdaQuery();
      wq.eq(SysUserPost::getUserId, loginUser.getSysUser().getId());
      List<SysUserPost> sysUserPosts = sysUserPostMapper.selectList(wq);
      List<Long> myPosts =
          sysUserPosts.stream().map(SysUserPost::getPostId).collect(Collectors.toList());
      LoginUser finalUser = loginUser;
      list.forEach(
          authRule -> {
            // 部门
            List<Long> depts =
                ObjUtil.isEmpty(authRule.getDeptIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getDeptIds(), Long.class);
            // 用户
            List<Long> users =
                ObjUtil.isEmpty(authRule.getUserIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getUserIds(), Long.class);
            // 角色
            List<Long> roles =
                ObjUtil.isEmpty(authRule.getRoleIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getRoleIds(), Long.class);
            // 岗位
            List<Long> posts =
                ObjUtil.isEmpty(authRule.getUserGroupIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getUserGroupIds(), Long.class);

            Collection intersection = CollectionUtil.intersection(posts, myPosts);
            if (depts.contains(finalUser.getDeptId())
                || users.contains(finalUser.getSysUser().getId())
                || roles.contains(finalUser.getRoleId())
                || !intersection.isEmpty()) {

              if (StrUtil.isNotBlank(authRule.getRuleExpress())
                  && JSONUtil.isTypeJSON(authRule.getRuleExpress())) {
                List<ConditionBO> conditionBO =
                    JSONUtil.toList(authRule.getRuleExpress(), ConditionBO.class);
                condition.addAll(conditionBO);
              }
            }
          });
    } catch (Exception e) {
      e.printStackTrace();
      log.info("异常，获取用户的特殊权限异常！" + e.getMessage());
    }
    return condition;
  }

  @Override
  public Set<ArchiveAuthRule> getAuthUseByUser(LoginUser loginUser) {
    loginUser = ObjUtil.isEmpty(loginUser) ? SecurityUtil.getLoginUser() : loginUser;
    if (ObjUtil.isEmpty(loginUser)) {
      throw BizTipException.instance(ErrorCode.NOT_FOUND, "找不到用户对象信息");
    }
    Set<ArchiveAuthRule> condition = new HashSet<>();
    try {
      List<ArchiveAuthRule> list = this.list();
      // 查询我这个用户的所有岗位
      LambdaQueryWrapper<SysUserPost> wq = Wrappers.lambdaQuery();
      wq.eq(SysUserPost::getUserId, loginUser.getSysUser().getId());
      List<SysUserPost> sysUserPosts = sysUserPostMapper.selectList(wq);
      List<Long> myPosts =
          sysUserPosts.stream().map(SysUserPost::getPostId).collect(Collectors.toList());
      LoginUser finalUser = loginUser;
      list.forEach(
          authRule -> {
            // 部门
            List<Long> depts =
                ObjUtil.isEmpty(authRule.getDeptIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getDeptIds(), Long.class);
            // 用户
            List<Long> users =
                ObjUtil.isEmpty(authRule.getUserIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getUserIds(), Long.class);
            // 角色
            List<Long> roles =
                ObjUtil.isEmpty(authRule.getRoleIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getRoleIds(), Long.class);
            // 岗位
            List<Long> posts =
                ObjUtil.isEmpty(authRule.getUserGroupIds())
                    ? Lists.newArrayList()
                    : IdUtil.split(authRule.getUserGroupIds(), Long.class);

            Collection intersection = CollectionUtil.intersection(posts, myPosts);
            if (depts.contains(finalUser.getDeptId())
                || users.contains(finalUser.getSysUser().getId())
                || roles.contains(finalUser.getRoleId())
                || !intersection.isEmpty()) {

              if (StrUtil.isNotBlank(authRule.getRuleExpress())
                  && JSONUtil.isTypeJSON(authRule.getRuleExpress())) {
                condition.add(authRule);
              }
            }
          });
    } catch (Exception e) {
      e.printStackTrace();
      log.info("异常，获取用户的特殊权限异常！" + e.getMessage());
    }
    return condition;
  }
}
